package com.qf.ability.gateway.filter;

import com.ken.event.action.apply.producer.EventTemplate;
import com.qf.ability.gateway.utils.ResponseUtils;
import com.qf.commons.data.result.R;
import com.qf.commons.data.result.RCodes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class RedRobFilter extends AbstractGatewayFilterFactory {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private String robredLua = "--抢红包的lua脚本\n" +
            "--接收红包id\n" +
            "local redid = KEYS[1]\n" +
            "--用户id\n" +
            "local uid = ARGV[1]\n" +
            "--红包的key\n" +
            "local key = 'red_envlopes_'..redid\n" +
            "\n" +
            "\n" +
            "--判断红包是否存在\n" +
            "local flag = redis.call('exists', key)\n" +
            "if flag == 0 then\n" +
            "   --红包不存在或者已经过期\n" +
            "   return -1\n" +
            "end\n" +
            "\n" +
            "--获取红包的部分参数\n" +
            "local type = tonumber(redis.call('hget', key, 'type'))\n" +
            "local score = tonumber(redis.call('hget', key, 'score'))\n" +
            "local count = tonumber(redis.call('hget', key, 'count'))\n" +
            "\n" +
            "--判断是否还能抢\n" +
            "if count == 0 then\n" +
            "  --红包已经抢完了\n" +
            "  return -2\n" +
            "end\n" +
            "\n" +
            "--判断是否存在当前的用户id\n" +
            "local flag2 = redis.call('hexists', key, 'user_'..uid)\n" +
            "if flag2 == 1 then\n" +
            "  -- 该用户已经抢过该红包\n" +
            "  return -3\n" +
            "end\n" +
            "\n" +
            "--抢到的积分值\n" +
            "local robScore = 0\n" +
            "\n" +
            "--进行抢红包的计算\n" +
            "if type == 0 then \n" +
            "    --固定红包\n" +
            "    robScore = score / count\n" +
            "else\n" +
            "    --随机红包\n" +
            "    if count == 1 then\n" +
            "         --最后一个人\n" +
            "         robScore = score\n" +
            "    else\n" +
            "         --不是最后一个人\n" +
            "         -- 设置随机种子\n" +
            "         local times = redis.call('time')\n" +
            "         math.randomseed(times[1] + times[2])\n" +
            "         -- 采用二倍均值法计算抢红包的积分数\n" +
            "         robScore = math.random(score / count * 2 - 1)\n" +
            "    end\n" +
            "end\n" +
            "\n" +
            "--更新本地的redis积分\n" +
            "redis.call('hmset', key, 'score', score - robScore, 'count', count - 1, 'user_'..uid, robScore)\n" +
            "return robScore";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            //获取当前的用户id
//            String uid = exchange.getRequest().getHeaders().getFirst("uid");
            String uid = (int)(Math.random() * 1000000) + "";
            //获取红包id
            String redid = exchange.getRequest().getQueryParams().getFirst("redid");
            log.debug("[rob red filter] 抢红包的过滤器! 用户id：{}  红包id：{}", uid, redid);

            //通过lua脚本
            Long result = redisTemplate.execute(new DefaultRedisScript<Long>(robredLua, Long.class),
                    Collections.singletonList(redid),
                    uid);

            if(result == -1){
                //红包已过期
                return ResponseUtils.responseOk(exchange, R.createFail(RCodes.RED_TIMEOUT, result));
            } else if(result == -2){
                //红包已经抢完
                return ResponseUtils.responseOk(exchange, R.createFail(RCodes.RED_OVER, result));
            } else if(result == -3){
                //红包已经抢过
                return ResponseUtils.responseOk(exchange, R.createFail(RCodes.RED_EXISTS, result));
            }

            //抢到红包
            Map<String, Integer> map = new HashMap<>();
            map.put("redid", Integer.parseInt(redid));
            map.put("uid", Integer.parseInt(uid));
            map.put("robScore", result.intValue());
            EventTemplate.sendReliable("rob-red", map);

            //返回结果
            return ResponseUtils.responseOk(exchange, R.create(result));
        };
    }

    @Override
    public String name() {
        return "RedRobFilter";
    }
}